package com.snap.update.update;

import android.app.Dialog;
import android.content.Context;
import android.view.View;
import android.widget.TextView;

import com.orhanobut.logger.Logger;
import com.snap.update.AppConfig;
import com.snap.update.MoleApplication;
import com.snap.update.R;
import com.snap.update.bean.SerialPortDevice;
import com.snap.update.framework.MoleExecutor;
import com.snap.update.utils.AESUtil;
import com.snap.update.utils.ToastUtils;

import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import static com.snap.update.AppConfig.SERIAL_BAUD_RATE;
import static com.snap.update.AppConfig.SERIAL_PORT;

public class UpdateManager {
    private UpdateSerialPortHelper serialPortHelper = new UpdateSerialPortHelper(new SerialPortDevice(SERIAL_PORT, SERIAL_BAUD_RATE));
    private ExecutorService singlePool = Executors.newSingleThreadExecutor();
    private List<UpdateConfigBean> configs;
    private boolean logEnable = true;

    private static UpdateManager sInstance = new UpdateManager();

    private UpdateManager() {
    }

    public static UpdateManager getInstance() {
        return sInstance;
    }

    /**
     * 升级到上位机必需的的最低下位机版本
     */
    public void updateMinimumRequired(Context context, String name) {
        Logger.e("开始固件更新");
        Dialog dialog = new Dialog(context, R.style.DialogStyle);
        dialog.setContentView(R.layout.update_dialog_loading);
        TextView contentTv = dialog.findViewById(R.id.content_tv);
        contentTv.setText("正在更新固件");
        TextView tipTv = dialog.findViewById(R.id.tip_tv);
        tipTv.setVisibility(View.VISIBLE);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(false);
        dialog.show();

        MoleExecutor.getInstance().execute(() -> {
            try {
                serialPortHelper.open();
                List<UpdateConfigBean> need = new ArrayList<>();
                HashMap<String, byte[]> binMap = new HashMap<>();
                for (int i = 0; i < 4; i++) {
                    UpdateConfigBean bean = new UpdateConfigBean();
                    bean.setIndex(i + 1);
                    bean.setName(name);
                    bean.setVersion(AppConfig.MINIMUM_HARD_VERSION_REQUIRED);
                    InputStream is = context.getAssets().open(name);
                    int length = is.available();
                    byte[] fileDate = new byte[length];
                    if (is.read(fileDate) != length) {
                        if (logEnable) Logger.e("未能读取文件" + name);
                    } else {
                        byte[] originFileData = AESUtil.decrypt(fileDate);
                        binMap.put(name, originFileData);
                        need.add(bean);
                    }
                }

                OnUpdateListener listener = new OnUpdateListener() {
                    @Override
                    public void onAnalyzeProcess(int cur, int total, double percent) {
                        contentTv.post(() -> {
                            String p = new DecimalFormat("#.#").format((percent + cur - 1) / total * 100) + "%";
                            contentTv.setText(String.format("固件更新中(%s)", p));
                            tipTv.setText(String.format("第%d个,共%d个", cur, total));
                        });
                    }
                };
                FutureTask<UpdateRes>[] futureTasks = new FutureTask[need.size()];
                for (int i = 0; i < need.size(); i++) {
                    UpdateTask2 task = new UpdateTask2(serialPortHelper, need.get(i).getIndex(),
                            binMap.get(need.get(i).getName()), need.get(i).getVersion());
                    task.setListener(i + 1, need.size(), listener);
                    singlePool.submit(futureTasks[i] = new FutureTask<>(task));
                }

                int updateCount = 0;
                for (int i = 0; i < futureTasks.length; i++) {
                    try {
                        UpdateRes res = futureTasks[i].get();
                        if (res.isSuc()) {
                            updateCount++;
                            AppConfig.Dynamic.hardwareVersion[i] = AppConfig.MINIMUM_HARD_VERSION_REQUIRED;
                            Logger.e("模块%d成功更新至%s", need.get(i).getIndex(), need.get(i).getVersion());
                        } else {
                            Logger.e("模块%d写入固件失败，原因：%s", need.get(i).getIndex(), res.getMsg());
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
                if (updateCount == 0) {
                    ToastUtils.get().showText("固件更新失败！请重启仪器后再次尝试！");
                } else {
                    ToastUtils.get().showText("固件更新成功");
                }
            } catch (IOException e) {
                Logger.e("固件更新失败！" + MoleApplication.printExceptionInfo(e));
                ToastUtils.get().showText("固件更新失败！请重启仪器后再次尝试！");
            } finally {
                serialPortHelper.close();
                dialog.dismiss();
            }
        });
    }
}
